package com.bobexchen.nettywebsocket;

import com.bobexchen.nettywebsocket.handler.NettyWebSocketHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class NettyServerHandlerInitializer extends ChannelInitializer<SocketChannel> {

    /**
     * 心跳超时时间
     */
    private static final Integer READ_TIMEOUT_SECONDS = 3 * 60;

    @Autowired
    private NettyWebSocketHandler nettyWebSocketHandler;


    //初始化通道
    //在这个方法中去加载对应的ChannelHandler
    @Override
    protected void initChannel(SocketChannel socketChannel) {

        //获取管道，将一个一个的ChannelHandler添加到管道中
        ChannelPipeline pipeline = socketChannel.pipeline();

        //设置log监听器，并且日志级别为debug，方便观察运行流程
        //pipeline.addLast(newLoggingHandler("DEBUG"));

        pipeline.addLast(new ReadTimeoutHandler(READ_TIMEOUT_SECONDS, TimeUnit.SECONDS))
                //设置解码器
                .addLast(new HttpServerCodec())
                //聚合器，使用websocket会用到
                .addLast(new HttpObjectAggregator(65536))
                //用于大数据的分区传输
                .addLast(new ChunkedWriteHandler())
                //自定义的业务handler
                .addLast(nettyWebSocketHandler)
                //验证协议url。
                //验证GET的请求升级。
                //替换当前处理器为forbiddenHttpRequestResponder。
                //创建握手WebSocketServerHandshaker对象，进行握手。
                //启动一个定义任务进行超时回调。
                .addLast(new WebSocketServerProtocolHandler("/ws", null, true, 65535, false, true));

        //增加心跳事件支持
        //第一个参数:读空闲4秒
        //第二个参数：写空闲8秒
        //第三个参数：读写空闲12秒
        //todo没生效
        pipeline.addLast(new IdleStateHandler(20, 20, 20));
    }

}
